#include <QtEndian>
#include "bankdataaccess.h"
#include "common/md5.h"
#include "common/idea.h"

bool BankDataAccess::checkData(void)
{
    ResponsePack *responsePack = (ResponsePack *)data_;
    quint16 cmd = qToBigEndian(responsePack->head.cmd);
    quint16 len = qToBigEndian(responsePack->head.len);
    // 计算hash
    unsigned char hash[16];
    MD5 md5;
    //sizeof(ResponsePack)并不是40的长度而是42,这里和对齐的方式有关
    //而这里校验应该取head来进行校验
    md5.MD5Make(hash, (quint8 const *)data_, sizeof(responsePack->head) + len - 8);
    for (int i = 0; i < 8; ++i)
    {
        hash[i] = hash[i] ^ hash[i+8];
        hash[i] = hash[i] ^ ((cmd >> (i%2)) & 0xff);
    }
    if (memcmp(hash, responsePack->buf + (len - 8), 8)) {
        return false;
    }
    return true;
}

void BankDataAccess::generatePackTailMd5(quint16 seed)
{
    unsigned char hash[16];
    MD5 md5;
    md5.MD5Make(hash, (unsigned char const*)jos_.Data(), jos_.Length());
    for (int i=0; i<8; ++i)
    {
        hash[i] = hash[i] ^ hash[i+8];
        hash[i] = hash[i] ^ ((seed >> (i%2)) & 0xff);
    }
    jos_.WriteBytes(hash, 8);
}

void BankDataAccess::encryPassword(QString &passStr,quint16 seed)
{
    unsigned char ideaKey[16];
    unsigned char buf[2];
    buf[0] = (seed >> 8) & 0xff;
    buf[1] = seed & 0xff;
    MD5 md5;
    md5.MD5Make(ideaKey, buf, 2);
    for (int i=0; i<8; ++i)
    {
        ideaKey[i] = ideaKey[i] ^ ideaKey[i+8];
        ideaKey[i] = ideaKey[i] ^ ((seed >> (i%2)) & 0xff);
        ideaKey[i+8] = ideaKey[i] ^ ideaKey[i+8];
        ideaKey[i+8] = ideaKey[i+8] ^ ((seed >> (i%2)) & 0xff);
    }
    char encryptedPass[16] = {0};
    Idea idea;
    // 加密
    const char *passData = (const char *)passStr.toLocal8Bit();
    idea.Crypt(ideaKey,(const quint8*)passData, (quint8 *)encryptedPass, 16, true);
    jos_.WriteBytes(encryptedPass, 16);
}
